package org.kjk.mail;

import java.io.IOException;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class GMail {
	private String user;
	private String pass;
	private String receivingHost;
	private Session session;

	public static Message[] message;
	public Store store;
	public Folder folder;

	// private int receivingPort;

	public GMail() {
		message = null;
		store = null;
		folder = null;
		user = null;
		pass = null;
	}

	public void setAccountDetails(String user, String pass) {
		this.user = user;// sender's email can also use as User Name
		this.pass = pass;
	}

	public class SMTPAuthenticator extends javax.mail.Authenticator {
		public String userName;
		public String passWord;

		public SMTPAuthenticator(String userName, String passWord) {
			this.userName = userName;
			this.passWord = passWord;
		}

		public PasswordAuthentication getPasswordAuthentication() {
			return new PasswordAuthentication(userName, passWord);
		}
	}

	public boolean postMail(String recipients[], String subject, String content) {
		boolean debug = false;
		// java.security.Security
		// .addProvider(new com.sun.net.ssl.internal.ssl.Provider());

		String SMTP_HOST_NAME = "gmail-smtp.l.google.com";
		// Properties
		Properties props = new Properties();
		props.put("mail.transport.protocol", "smtp");
		props.put("mail.smtp.starttls.enable", "true");
		props.put("mail.smtp.host", SMTP_HOST_NAME);
		props.put("mail.smtp.auth", "true");
		props.put("mail.smtp.user", this.user);
		props.put("mail.smtp.password", this.pass);
		Session session1 = Session.getDefaultInstance(props, new SMTPAuthenticator(user, pass));
		session1.setDebug(debug);

		// create a message
		Message msg = new MimeMessage(session1);
		// set the from and to address
		InternetAddress addressFrom;
		try {
			addressFrom = new InternetAddress(this.user);
			msg.setFrom(addressFrom);
			InternetAddress[] addressTo = new InternetAddress[recipients.length];
			for (int i = 0; i < recipients.length; i++) {
				addressTo[i] = new InternetAddress(recipients[i]);
			}
			msg.setRecipients(Message.RecipientType.TO, addressTo);

			// Setting the Subject and Content Type
			msg.setSubject(subject);
			msg.setContent(content, "text/plain;charset=\"utf-8\"");
			Transport.send(msg);
		} catch (AddressException e) {
			e.printStackTrace();
			return false;
		} catch (MessagingException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public boolean sendGmail(String to[], String subject, String content) {
		Properties props = new Properties();
		props.put("mail.smtp.host", "smtp.gmail.com");
		props.put("mail.smtp.port", 465);
		props.put("mail.smtp.user", this.user);
		props.put("mail.smtp.password", this.pass);
		props.put("mail.smtp.auth", "true");

		Session session1 = Session.getDefaultInstance(props,
				new Authenticator() {
					@Override
					protected PasswordAuthentication getPasswordAuthentication() {
						return new PasswordAuthentication(user, pass);
					}
				});
		Message simpleMessage = new MimeMessage(session1);
		InternetAddress fromAddress = null;
		InternetAddress[] toAddress = null;
		try {
			fromAddress = new InternetAddress(this.user);
			toAddress = new InternetAddress[to.length];
			for (int i = 0; i < to.length; i++) {
				toAddress[i] = new InternetAddress(to[i]);
			}
			simpleMessage.setFrom(fromAddress);
			simpleMessage.setRecipients(Message.RecipientType.TO, toAddress);

			simpleMessage.setSubject(subject);
			// simpleMessage.setContent(content,
			// "text/plain;charset=\"utf-8\"");
			simpleMessage.setText(content); // sometimes
			// Transport.send(simpleMessage); is used, but for gmail it's
			// different
			Transport transport = session.getTransport("smtps");
			transport.connect("smtp.gmail.com", 465, user, pass);
			transport.sendMessage(simpleMessage,
					simpleMessage.getAllRecipients());
			transport.close();
		} catch (AddressException e) {
			e.printStackTrace();
			return false;
		} catch (MessagingException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public void closeMail() throws MessagingException {
		folder.close(true);
		store.close();
	}

	public void readForce() {
		this.receivingHost = "imap.gmail.com";// for imap protocol
		Properties props2 = System.getProperties();
		props2.setProperty("mail.store.protocol", "imaps");
		// I used imaps protocol here
		session = Session.getDefaultInstance(props2, new SMTPAuthenticator(
				this.user, this.pass));
		try {
			store = session.getStore("imaps");
			store.connect(this.receivingHost, this.user, this.pass);
			folder = store.getFolder("INBOX");// get inbox
			folder.open(Folder.READ_ONLY);// open folder only to read
			message = folder.getMessages();
			// for (int i = 0; i < message.length; i++) {
			// System.out.println(message[i].getSubject());
			// System.out.println("\t" + message[i].getContent());
			// }
		} catch (Exception e) {
			System.out.println(e.toString());
		}
	}

	public void readGmail() {
		refreshData();
		try {
			for (int i = 0; i < message.length; i++) {
				// print subjects of all mails in the inbox
				System.out.println(message[i].getSubject());
				System.out.println("\t" + message[i].getContent());
			}
		} catch (MessagingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public List<GMailDTO> getSubject() throws Exception {
		refreshData();
		List<GMailDTO> result = new ArrayList<GMailDTO>();
		try {
			if (message == null) {
				return null;
			}
			for (int i = 0; i < message.length; i++) {
				GMailDTO dto = new GMailDTO(message[i], i);
				result.add(dto);
			}
		} catch (MessagingException e) {
			e.printStackTrace();
		}
		return result;
	}

	public JSONObject getJsonSubject() throws JSONException {
		refreshData();
		JSONObject json = null;
		JSONArray arr = new JSONArray();
		Format formatter = new SimpleDateFormat("yyyyMMdd/HH:mm");
		try {
			if (message == null) {
				return json;
			}
			json = new JSONObject();
			json.put("result", arr);
			for (Message msg : message) {
				StringBuilder str = new StringBuilder();
				for (Address addr : msg.getFrom()) {
					str.append(addr.toString() + "; ");
				}
				JSONObject obj = new JSONObject();
				obj.put("sender", str.toString());
				obj.put("subject", msg.getSubject());
				obj.put("attachment", msg.getFileName());
				obj.put("receivedDate", formatter.format(msg.getReceivedDate()));
				arr.put(obj);
			}
		} catch (MessagingException e) {
			e.printStackTrace();
		}
		return json;
	}

	public void refreshData() {
		if (message == null || message.length == 0) {
			readForce();
		}
	}

	public String getContent(int index) {
		refreshData();
		try {
			return message[index].getContent().toString();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		}
		return "fail to read";
	}

	public void deleteMessage(Message m) throws MessagingException {
		m.setFlag(Flags.Flag.DELETED, true);
		// if (m.isSet(Flags.Flag.DELETED))
		// System.out.println("DELETED message");
	}

	public static void main(String[] args) {
		String mailFrom = new String("kjkjjang@gmail.com");
		// Sender must be a Gmail Account holder
		String mailTo = new String("kjkjjang@gmail.com");
		// but here you can send to any type of mail account
		String senderPassword = new String("rlawlsry85");
		String senderUserName = new String("kjkjjang");
		// Mention your email subject and content
		String mailSubject = new String("Testing Mail");
		String mailText = new String("Have an Nice Day ...........!!!");
		// Create a GmailClient object
		GMail newGmailClient = new GMail();
		// Setting up account details
		newGmailClient.setAccountDetails(senderUserName, senderPassword);
		newGmailClient.readGmail();
		// newGmailClient.sendGmail(mailFrom, mailTo, mailSubject, mailText);
	}
}
